'use strict'
const path = require('path')
const defaultSettings = require('./src/settings.js')

function resolve (dir) {
  return path.join(__dirname, dir)
}

const name = defaultSettings.title || '人力资源管理' // page title

const port = process.env.port || process.env.npm_config_port || 9528 // dev port

// 准备CDN链接
let externals = {}
let cdn = { css: [], js: [] }
const isProduction = process.env.NODE_ENV === 'production' // 判断是否是生产环境
if (isProduction) {
  // 配置CND
  externals = {
    // key(要排除的包名), value(引入的CDN包的全局变量名)
    'vue': 'Vue',
    'element-ui': 'ELEMENT',
    'xlsx': 'XLSX',
    'moment': 'moment'
  }
  cdn = {
    css: [
      'https://unpkg.com/element-ui/lib/theme-chalk/index.css' // element-ui css 样式表
    ],
    js: [
      // vue must at first!
      // 'https://unpkg.com/vue/dist/vue.js', // vuejs  老师的cdn地址,错误的!!!
      'https://cdn.bootcss.com/vue/2.6.11/vue.min.js', // 自己百度查询的Vue的cdn地址
      'https://unpkg.com/element-ui/lib/index.js', // element-ui js
      'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/jszip.min.js',
      'https://cdn.jsdelivr.net/npm/xlsx@0.16.6/dist/xlsx.full.min.js',
      'https://cdn.bootcdn.net/ajax/libs/moment.js/2.29.1/moment.min.js'
    ]
  }
}

// 配置说明官网: https://cli.vuejs.org/config/
module.exports = {

  publicPath: './',
  // build时放置生成的静态资源 (js、css、img、fonts) 的 (相对于 outputDir 的) 目录
  outputDir: 'dist', // 位置
  assetsDir: 'static', // 文件名

  // 是否在开发环境下通过 eslint-loaderes 检查 (true为先查 false为不检查)
  lintOnSave: process.env.NODE_ENV === 'development',
  // 打包时不生成Map文件
  productionSourceMap: false,

  // // 开发模式下服务器设置
  // 配置说明:https://cli.vuejs.org/zh/config/index.html#devserver
  devServer: {
    port: port,
    open: true,
    overlay: {
      warnings: false,
      errors: true
    },
    /* 跨域代理 */
    proxy: {
      // 所有的接口调用中路径以/api开头的请求被代理到target指向的位置
      // 本来请求：http://localhost:9528/api/sys/profile
      // 真实请求：http://ihrm-java.itheima.net/sys/profile
      '^/api': {
        target: 'http://ihrm.itheima.net'
        // pathRewrite: {
        //   '^/api': '' // pathRewrite 表示的意思是 把/api 替换为空
        // }
      }
    }
    // before: require('./mock/mock-server.js')
  },

  // 如果这个值是一个对象，则会通过 webpack-merge 合并到最终的配置中。https://cli.vuejs.org/zh/config/index.html#configurewebpack
  configureWebpack: {
    name: name,
    // 排除打包(当是生产模式才会给externals赋值,也就相当于生产模式才排除打包)
    externals: externals,

    resolve: {
      alias: {
        '@': resolve('src')
      }
    }
  },
  // 是一个函数，会接收一个基于 webpack-chain 的 ChainableConfig 实例。允许对内部的 webpack 配置进行更细粒度的修改。 https://cli.vuejs.org/zh/config/index.html#chainwebpack
  chainWebpack (config) {
    // 开启预加载preload (提前预加载提高切换路由的体验)
    config.plugin('preload').tap(() => [
      {
        rel: 'preload',
        // https://github.com/vuejs/vue-cli/blob/dev/packages/@vue/cli-service/lib/config/app.js#L171
        fileBlacklist: [/\.map$/, /hot-update\.js$/, /runtime\..*\.js$/],
        include: 'initial'
      }
    ])

    // 使用 配置好的CND******************
    // 注入cdn变量给HTML页面 (打包时会执行)https://cli.vuejs.org/zh/guide/webpack.html#%E4%BF%AE%E6%94%B9%E6%8F%92%E4%BB%B6%E9%80%89%E9%A1%B9
    config.plugin('html').tap(args => {
      args[0].cdn = cdn // 配置cdn给插件
      return args
    })

    // 移除 prefetch 插件 Vue CLI 应用默认为所有作为 async chunk 生成的 JavaScript 文件 (通过动态 import() 按需 code splitting 的产物) 自动生成prefetch提示；相关百度资料: https://www.csdn.net/tags/MtTaEg4sNDQ0Mjk5LWJsb2cO0O0O.html
    config.plugins.delete('prefetch') // 开启预加载preload,则需要关闭prefetch

    // 设置svg精灵图icons字体图标
    config.module
      .rule('svg')
      .exclude.add(resolve('src/icons'))
      .end()
    config.module
      .rule('icons')
      .test(/\.svg$/)
      .include.add(resolve('src/icons'))
      .end()
      .use('svg-sprite-loader')
      .loader('svg-sprite-loader')
      .options({
        symbolId: 'icon-[name]'
      })
      .end()

    // .when 当不是开发模式下执行(也就是生产模式下执行)**********************
    config
      .when(process.env.NODE_ENV !== 'development',
        // 百度教程: https://blog.csdn.net/qq_21567385/article/details/107634781

        // script-ext-html-webpack-plugin
        // 下载插件: yarn add -D html-webpack-plugin script-ext-html-webpack-plugin
        // 接下来使用链式 webpack 语法配置
        config => {
          config
            .plugin('ScriptExtHtmlWebpackPlugin')
            .after('html')
            .use('script-ext-html-webpack-plugin', [{
              // `runtime` must same as runtimeChunk name. default is `runtime`
              inline: /runtime\..*\.js$/
            }])
            .end()

          // chunks 资源分块
          // 如果使用了某些长期不会改变的库，像 element - ui ，打包完成有 600 多 KB ，包含在默认 vendor 中显然不合适，每次用户都要加载这么大的文件体验不好，所以要单独打包：
          config
            .optimization.splitChunks({
              chunks: 'all',
              cacheGroups: {
                libs: {
                  name: 'chunk-libs',
                  test: /[\\/]node_modules[\\/]/,
                  priority: 10,
                  chunks: 'initial' // only package third parties that are initially dependent
                },
                elementUI: {
                  name: 'chunk-elementUI', // split elementUI into a single package
                  priority: 20, // the weight needs to be larger than libs and app or it will be packaged into libs or app
                  test: /[\\/]node_modules[\\/]_?element-ui(.*)/ // in order to adapt to cnpm
                },
                commons: {
                  name: 'chunk-commons',
                  test: resolve('src/components'), // can customize your rules
                  minChunks: 3, //  minimum common number
                  priority: 5,
                  reuseExistingChunk: true
                }
              }
            })
          // runtime.js 处理策略
          // 根据路由驱动页面的 runtime 代码默认情况是包含在 build 后的 app.hash.js 内的，如果我们改动其他路由，就会导致 runtime 代码改变。从而不光我们改动的路由对应的页面 js 会变，含 runtime 代码的 app.hash.js 也会变，对用户体验是非常不友好的。
          // 为了解决这个问题要设定 runtime 代码单独抽取打包：
          config.optimization.runtimeChunk('single')

          // 在项目打包上线后，去除掉代码中所有的console.log
          config.optimization.minimizer('terser').tap((args) => {
            args[0].terserOptions.compress.drop_console = true
            return args
          })
        }
      )
  }
}

